﻿Imports WiremetModel.Entities.SupplyOrders
Imports WiremetModel.Entities.OEM
Imports InputValidation
Imports InputValidation.GeneralRules
Imports InputValidation.GeneralRules.NumericInputRules
Imports System.ComponentModel

Public Class MiscellaneousOrderLineInputDialog

    Private _unitOfWork As UnitOfWork
    Private _productTypeList As IEnumerable(Of ProductType)
    Private _productList As IEnumerable(Of Product)
    Private _miscellaneousOrderLine As MiscellaneousOrderLine
    Public Property MiscellaneousOrderLine() As MiscellaneousOrderLine
        Get
            Return _miscellaneousOrderLine
        End Get
        Set(ByVal value As MiscellaneousOrderLine)
            _miscellaneousOrderLine = value
        End Set
    End Property

    Private _inputValidator As InputValidator


    Public Sub New(ByRef unitOfWork As UnitOfWork)
        InitializeComponent()
        ClearErrorLabels()
        '_unitOfWork = New UnitOfWork()
        _unitOfWork = unitOfWork
        _inputValidator = New InputValidator()
        _miscellaneousOrderLine = New MiscellaneousOrderLine()
        RefreshViewData()
    End Sub

    Public Sub New(ByRef unitOfWork As UnitOfWork, ByVal miscellaneousOrderLine As MiscellaneousOrderLine)
        Me.New(unitOfWork)

        cmb_ProductType.Text = miscellaneousOrderLine.Product.ProductType.Name
        cmb_Product.Text = miscellaneousOrderLine.Product.Name
        tb_Quantity.Text = miscellaneousOrderLine.Quantity.ToString()
        cmb_MeasureUnit.Text = miscellaneousOrderLine.MeasureUnit.Jednostka
        tb_UnitPrice.Text = miscellaneousOrderLine.UnitPrice.ToString()

        _miscellaneousOrderLine = miscellaneousOrderLine
    End Sub

    'Private Sub MiscellaneousOrderLineInputDialog_FormClosed(ByVal sender As Object, ByVal e As FormClosedEventArgs) Handles Me.FormClosed
    '    _unitOfWork.Dispose()
    'End Sub

    Private Sub ClearErrorLabels()
        lbl_MeasureUnitError.Text = String.Empty
        lbl_ProductError.Text = String.Empty
        lbl_ProductTypeError.Text = String.Empty
        lbl_QuantityError.Text = String.Empty
        lbl_UnitPriceError.Text = String.Empty
    End Sub

    Private Sub RefreshViewData()

        Dim productTypeRepository As New Repository(Of ProductType)(_unitOfWork)
        Dim productRepository As New Repository(Of Product)(_unitOfWork)
        Dim measureUnitRepository As New Repository(Of JednostkaMiary)(_unitOfWork)

        _productTypeList = productTypeRepository.GetAll()
        _productList = productRepository.GetAll()
        Dim measureUnitList As IEnumerable(Of JednostkaMiary) = measureUnitRepository.GetAll()


        InitializeInputComboBox(cmb_ProductType, _productTypeList)
        'InitializeInputComboBox(cmb_Product, _productList, "Name", _productList.Select(Function(x) x.Name).ToArray())
        InitializeInputComboBox(cmb_MeasureUnit, measureUnitList)

    End Sub

    Private Sub InitializeInputComboBox(ByRef inputComboBox As ComboBox, ByVal data As IEnumerable(Of Object))
        inputComboBox.DataSource = New BindingSource(data, Nothing)
        inputComboBox.AutoCompleteCustomSource.Clear()
        inputComboBox.AutoCompleteCustomSource.AddRange(data.Select(Function(x) x.ToString()).ToArray())
        inputComboBox.SelectedIndex = -1
    End Sub


    'Private Sub InitializeInputComboBox(ByRef inputComboBox As ComboBox, ByVal data As IEnumerable(Of Object), ByVal displayMember As String, ByVal autoCompleteCustomSource As String())
    '    inputComboBox.DataSource = New BindingSource(data, Nothing)
    '    inputComboBox.DisplayMember = displayMember
    '    inputComboBox.AutoCompleteCustomSource.Clear()
    '    inputComboBox.AutoCompleteCustomSource.AddRange(autoCompleteCustomSource)
    '    inputComboBox.SelectedIndex = -1
    'End Sub


#Region "Input validation"

    Private Sub cmb_ProductType_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles cmb_ProductType.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        _inputValidator.ValidateComboBox(cmb_ProductType, e, lbl_ProductTypeError, notNullableTextInputValidatingSpecification)
    End Sub

    Private Sub cmb_Product_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles cmb_Product.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        _inputValidator.ValidateComboBox(cmb_Product, e, lbl_ProductError, notNullableTextInputValidatingSpecification)
    End Sub

    Private Sub tb_Quantity_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles tb_Quantity.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        Dim numericPositiveInputValidatingSpecification As New NumericPositiveInputValidatingSpecification()
        _inputValidator.ValidateTextBox(tb_Quantity, e, lbl_QuantityError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification).And(numericPositiveInputValidatingSpecification))
    End Sub

    Private Sub cmb_MeasureUnit_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles cmb_MeasureUnit.Validating
        Dim NotNullableComboBoxValidatingSpecification As New NotNullableComboBoxValidatingSpecification(Of JednostkaMiary)
        _inputValidator.ValidateComboBox(cmb_MeasureUnit, e, lbl_MeasureUnitError, NotNullableComboBoxValidatingSpecification)
    End Sub

    Private Sub tb_UnitPrice_Validating(ByVal sender As Object, ByVal e As CancelEventArgs) Handles tb_UnitPrice.Validating
        Dim notNullableTextInputValidatingSpecification As New NotNullableTextInputValidatingSpecification()
        Dim numericInputValidatingSpecification As New NumericInputValidatingSpecification()
        Dim numericPositiveInputValidatingSpecification As New NumericPositiveInputValidatingSpecification()
        _inputValidator.ValidateTextBox(tb_UnitPrice, e, lbl_UnitPriceError, notNullableTextInputValidatingSpecification.And(numericInputValidatingSpecification).And(numericPositiveInputValidatingSpecification))
    End Sub

    Private Sub cmb_ProductType_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles cmb_ProductType.Validated
        lbl_ProductTypeError.Text = String.Empty
    End Sub

    Private Sub cmb_Product_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles cmb_Product.Validated
        lbl_ProductError.Text = String.Empty
    End Sub

    Private Sub tb_Quantity_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles tb_Quantity.Validated
        lbl_QuantityError.Text = String.Empty
    End Sub

    Private Sub cmb_MeasureUnit_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles cmb_MeasureUnit.Validated
        lbl_MeasureUnitError.Text = String.Empty
    End Sub

    Private Sub tb_UnitPrice_Validated(ByVal sender As Object, ByVal e As EventArgs) Handles tb_UnitPrice.Validated
        lbl_UnitPriceError.Text = String.Empty
    End Sub

#End Region


    Private Sub cmb_ProductType_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmb_ProductType.SelectedIndexChanged
        cmb_ProductType.Text = cmb_ProductType.Text.Trim()
        If IsNothing(cmb_ProductType.SelectedItem) Then
            InitializeInputComboBox(cmb_Product, _productList)
        Else
            InitializeInputComboBox(cmb_Product, CType(cmb_ProductType.SelectedItem, ProductType).Products)
        End If
    End Sub

    'Private Sub cmb_Product_SelectedIndexChanged(sender As System.Object, e As System.EventArgs) Handles cmb_Product.SelectedIndexChanged
    '    cmb_Product.Text = cmb_Product.Text.Trim()
    '    Dim selectedProduct As Product = CType(cmb_Product.SelectedItem, Product)
    '    Dim selectedProductType As ProductType = CType(cmb_ProductType.SelectedItem, ProductType)

    '    If Not IsNothing(selectedProductType) Then
    '        If IsNothing(selectedProduct) Then
    '            'cmb_ProductType.Text = String.Empty
    '        Else
    '            cmb_ProductType.Text = selectedProduct.ProductType.Name
    '        End If
    '    End If
    'End Sub



    Private Function GetSelectedProductType() As ProductType
        cmb_ProductType.Text = cmb_ProductType.Text.Trim()
        Dim selectedProductType As ProductType = CType(cmb_ProductType.SelectedItem, ProductType)
        If IsNothing(selectedProductType) Then
            selectedProductType = New ProductType With {
                .Name = cmb_ProductType.Text.Trim()
            }

            Dim productTypeRepository As New Repository(Of ProductType)(_unitOfWork)
            _unitOfWork.BeginTransaction()
            productTypeRepository.Add(selectedProductType)
            _unitOfWork.CommitTransaction()

        End If

        Return selectedProductType
    End Function


    Private Function GetSelectedProduct(ByVal selectedProductType As ProductType) As Product
        cmb_Product.Text = cmb_Product.Text.Trim()
        Dim selectedProduct As Product = CType(cmb_Product.SelectedItem, Product)
        If IsNothing(selectedProduct) OrElse selectedProduct.ProductType.Id <> selectedProductType.Id Then
            selectedProduct = New Product With {
                .Name = cmb_Product.Text.Trim(),
                .ProductType = selectedProductType
            }

            Dim productRepository As New Repository(Of Product)(_unitOfWork)
            _unitOfWork.BeginTransaction()
            productRepository.Add(selectedProduct)
            _unitOfWork.CommitTransaction()
        End If

        Return selectedProduct
    End Function


    Private Sub btn_Accept_Click(sender As System.Object, e As System.EventArgs) Handles btn_Accept.Click
        Try
            If Not ValidateChildren() Then
                Throw New EntityDataInputException("Podane dane są nieprawidłowe." & vbNewLine &
                                                   "Popraw je i spróbuj ponownie.")
            End If

            Dim confirmationDialogResult As DialogResult = MessageBox.Show("Czy jesteś pewień?", "Uwaga!", MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
            If confirmationDialogResult = Windows.Forms.DialogResult.Yes Then


                With MiscellaneousOrderLine
                    .MeasureUnit = CType(cmb_MeasureUnit.SelectedItem, JednostkaMiary)
                    .Product = GetSelectedProduct(GetSelectedProductType())
                    .Quantity = Integer.Parse(tb_Quantity.Text.Trim())
                    .UnitPrice = Decimal.Parse(tb_UnitPrice.Text.Trim())
                End With


                DialogResult = Windows.Forms.DialogResult.OK
            End If
        Catch ex As EntityDataInputException
            MessageBox.Show(ex.Message, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning)
        Catch ex As Exception
            MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub

    Private Sub btn_Cancel_Click(sender As System.Object, e As System.EventArgs) Handles btn_Cancel.Click
        DialogResult = Windows.Forms.DialogResult.Cancel
    End Sub

    Private Function GetTotalCost() As Decimal
        If IsNumeric(tb_Quantity.Text.Trim()) AndAlso IsNumeric(tb_UnitPrice.Text.Trim()) Then
            Return Math.Round(Decimal.Parse(tb_Quantity.Text.Trim()) * Decimal.Parse(tb_UnitPrice.Text.Trim()), 2)
        Else
            Return 0
        End If
    End Function

    Private Sub UpdateTotalCost(sender As System.Object, e As System.EventArgs) Handles tb_Quantity.TextChanged, tb_UnitPrice.TextChanged
        tb_TotalCost.Text = GetTotalCost().ToString()
    End Sub

End Class